package com.syni.mdd.yhd.common.all.service.pay.wxPay;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.ijpay.core.enums.SignType;
import com.ijpay.core.kit.HttpKit;
import com.ijpay.core.kit.IpKit;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.WxPayApiConfig;
import com.ijpay.wxpay.WxPayApiConfigKit;
import com.ijpay.wxpay.model.*;
import com.syni.mdd.yhd.common.all.config.pay.wxPay.WxPayBean;
import com.syni.mdd.yhd.common.all.config.pay.wxPay.WxPayBeanFactory;
import com.syni.mdd.yhd.common.all.constants.Constants;
import com.syni.mdd.yhd.common.all.constants.ResultCode;
import com.syni.mdd.yhd.common.all.constants.ResultMsg;
import com.syni.mdd.yhd.common.all.entity.BmsDxGroupBuyUse;
import com.syni.mdd.yhd.common.all.entity.BmsDxOrder;
import com.syni.mdd.yhd.common.all.entity.bo.wxPay.WxRefundQueryBo;
import com.syni.mdd.yhd.common.all.entity.pay.wxmodel.ReceiversModel;
import com.syni.mdd.yhd.common.all.entity.record.ReOrderRefundLog;
import com.syni.mdd.yhd.common.all.entity.record.ReTransferLog;
import com.syni.mdd.yhd.common.all.entity.user.BmsUser;
import com.syni.mdd.yhd.common.all.listen.order.OrderEvent;
import com.syni.mdd.yhd.common.all.listen.order.OrderRefundCompleteListener;
import com.syni.mdd.yhd.common.all.service.BmsCommonService;
import com.syni.mdd.yhd.common.all.service.BmsDxGroupBuyUseService;
import com.syni.mdd.yhd.common.all.service.BmsDxOrderService;
import com.syni.mdd.yhd.common.all.service.BmsUserService;
import com.syni.mdd.yhd.common.all.service.pay.aiPay.AliPayService;
import com.syni.mdd.yhd.common.all.service.record.ReTransferLogService;
import com.syni.mdd.sjb.common.component.utils.common.utils.ArithUtil;
import com.syni.mdd.yhd.common.all.utils.RequestParamUtils;
import com.syni.mdd.yhd.common.all.utils.RestTemplateUtils;
import com.syni.mdd.yhd.common.all.utils.StringUtils;
import com.syni.mdd.sjb.common.component.utils.common.spring.ApplicationContextHolder;
import com.syni.mdd.sjb.common.component.utils.common.utils.DateTimeUtils;
import com.syni.mdd.sjb.common.component.utils.common.utils.ParamsMap;
import com.syni.mdd.sjb.common.component.utils.common.utils.ResultMapHelper;
import com.syni.mdd.sjb.common.component.utils.common.utils.WebUtils;
import com.syni.mdd.sjb.common.component.utils.redis.utils.RedisTemplateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

;

/**
 * @className WxPayServiceImpl
 * @description TOO
 * @Author cfx
 * @DATE 2019/11/24 11:42
 * @VERSION 1.0
 **/
@Service
public class WxPayService {

    //公众号支付
    final int PUBLIC_PAY = 2;

    @Autowired
    BmsDxOrderService bmsDxOrderService;

    @Autowired
    private AliPayService aliPayService;

    @Autowired
    BmsDxGroupBuyUseService bmsDxGroupBuyUseService;

    @Autowired
    ReTransferLogService reTransferLogService;

    @Autowired
    BmsUserService bmsUserService;

    private final Logger log = LoggerFactory.getLogger(getClass());

    public void payNotify(Map<String,String> resultParams) {
        String info = JSON.toJSONString(resultParams);
        String out_trade_no = resultParams.get("out_trade_no");
        String transaction_id = resultParams.get("transaction_id");
        log.info("微信支付回调成功：" + info);
        //执行回调逻辑
        Date nowTime = new Date();
        try {
            //TODO
            // 修改订单状态
            // 已缴费----开始处理业务
            //orderLog.setCallBackIsSuccess(Constants.COMMON_FLAG_TRUE_INT);
            log.info(out_trade_no +" 用户已付款：.................................." );
            BmsDxOrder bmsDxOrder = bmsDxOrderService.getBaseDao().findByOrderNo(out_trade_no);
            bmsDxOrder.setTransactionId(transaction_id);
            bmsDxOrder.setPayWay(Constants.WX_PAY);
            bmsDxOrderService.getBaseDao().save(bmsDxOrder);
            if(aliPayService.orderPayHand(info,bmsDxOrder,nowTime)){
                bmsDxOrder.setPayTime(nowTime);
                bmsDxOrderService.getBaseDao().save(bmsDxOrder);
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            log.error("WxPay callBack error：",e);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public Map<String,Object> refund(WxPayApiConfig wxPayApiConfig,String notifyUrl, ParamsMap paramsMap) throws Exception {
        Map<String,Object> handleMap = bmsDxOrderService.userRefundOrderOrder(paramsMap);
        if(!ResultCode.CODE_NORMAL.equals(handleMap.get("status").toString())){
            return handleMap;
        }
        BmsDxOrder bmsDxOrder = (BmsDxOrder) handleMap.get("data");
        Map<String,Object> userDataMap = (Map<String, Object>) handleMap.get("userData");
        //执行微信退款
        //订单总金额
        Double orderTotal = ArithUtil.round(ArithUtil.mul(bmsDxOrder.getActualConsum(),100),0);
        String orderTotalFee = String.valueOf(orderTotal.intValue());
        //退款金额
        Double orderRefund = Double.parseDouble(userDataMap.get("refundTotal").toString());
        orderRefund = ArithUtil.round(ArithUtil.mul(orderRefund,100),0);
        String orderRefundFee = String.valueOf(orderRefund.intValue());

        Map<String, String> params = RefundModel.builder()
                .appid(wxPayApiConfig.getAppId())
                .mch_id(wxPayApiConfig.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .out_trade_no(bmsDxOrder.getOrderNo())
                .out_refund_no(WxPayKit.generateStr())
                .total_fee(orderTotalFee)
                .refund_fee(orderRefundFee)
                .notify_url(notifyUrl)
                .build()
                .createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5);
        List<BmsDxGroupBuyUse> groupBuyUseList = (List<BmsDxGroupBuyUse>) userDataMap.get("bmsDxGroupBuyUses");
        //存储处理时间
        Date nowTime = new Date();
        for(BmsDxGroupBuyUse bmsDxGroupBuyUse : groupBuyUseList){
            bmsDxGroupBuyUse.setAcceptTime(nowTime);
        }
        String xmlResult = WxPayApi.orderRefund(false, params, wxPayApiConfig.getCertPath(), wxPayApiConfig.getMchId());
        Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
        log.info("退款结果：" + JSON.toJSONString(result));
        String returnCode = result.get("return_code");
        String returnMsg = result.get("return_msg");
        if(bmsDxOrder.getTransactionId() != null) {
            if (!(WxPayKit.codeIsOk(returnCode) && "SUCCESS".equals(result.get("result_code")))) {
                throw new Exception("api接口调用失败");
            }
            for (BmsDxGroupBuyUse bmsDxGroupBuyUse : groupBuyUseList) {
                bmsDxGroupBuyUse.setRefundTime(nowTime);
            }
        }else {
            for (BmsDxGroupBuyUse bmsDxGroupBuyUse : groupBuyUseList) {
                bmsDxGroupBuyUse.setRefundTime(nowTime);
            }
        }
        userDataMap.put("refundTime", DateTimeUtils.converDateToString(groupBuyUseList.get(0).getRefundTime(),DateTimeUtils.DATE_PATTERN_DAY_05));
        userDataMap.put("refundNum",groupBuyUseList.size());
        //保存状态和时间
        bmsDxGroupBuyUseService.getBaseDao().saveAll(groupBuyUseList);
        //发送消息
        BmsCommonService.getApplicationContext().publishEvent(new OrderEvent("orderRefund",bmsDxOrder,userDataMap));
        return ResultMapHelper.success(userDataMap, ResultMsg.CODE_ORDER_RUFUND_SUCCESS);
    }

    public WxPayBean getApiConfigByChannel(String channel) {
        return WxPayBeanFactory.getProperties(channel);
    }

    public boolean refundMoney(BmsDxOrder bmsDxOrder, Double orderRefund,List<BmsDxGroupBuyUse> buyUses,WxPayBean wxPayApiConfig) {
        //执行微信退款
        //订单总金额
        Double orderTotal = ArithUtil.round(ArithUtil.mul(bmsDxOrder.getActualConsum(),100),0);
        String orderTotalFee = String.valueOf(orderTotal.intValue());
        //退款金额
        orderRefund = ArithUtil.round(ArithUtil.mul(orderRefund,100),0);
        if(orderRefund > 0d) {
            String orderRefundFee = String.valueOf(orderRefund.intValue());
            Map<String, String> params = RefundModel.builder()
                    .appid(wxPayApiConfig.getAppId())
                    .mch_id(wxPayApiConfig.getMchId())
                    .nonce_str(WxPayKit.generateStr())
                    .out_trade_no(bmsDxOrder.getOrderNo())
                    .out_refund_no(WxPayKit.generateStr())
                    .total_fee(orderTotalFee)
                    .refund_fee(orderRefundFee)
                    .notify_url(wxPayApiConfig.getRefundNotifyUrl())
                    .build()
                    .createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5);
            String xmlResult = WxPayApi.orderRefund(false, params, wxPayApiConfig.getCertPath(), wxPayApiConfig.getMchId());
            Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
            log.info("wxPay refund result：" + JSON.toJSONString(result));
            String returnCode = result.get("return_code");
            if (bmsDxOrder.getTransactionId() != null && WxPayKit.codeIsOk(returnCode)) {
                String result_code = result.get("result_code");
                if("FAIL".equals(result_code)){
                    String err_code_des = result.get("err_code_des");
                    if("订单已全额退款".equals(err_code_des)){
                        log.info("订单id:{},订单已全额退款",bmsDxOrder.getId());
                        return true;
                    }
                }
                if("SUCCESS".equals(result_code)){
                    String refundId = result.get("refund_id");
                    //存一下退款订单号
                    bmsDxGroupBuyUseService.addRefundId(buyUses,refundId);
                    //查询是否真的退款成功
                    WxRefundQueryBo wxRefundQueryBo = this.refundQuery(refundId,WxPayBeanFactory.MIN_APP_CHANNEL);
                    if(wxRefundQueryBo.checkStatus()){
                        Double refundFree = Double.parseDouble(wxRefundQueryBo.getRefundFee());
                        if(refundFree.equals(orderRefund)){
                            //添加一条退款监听
                            BmsCommonService.getApplicationContext().publishEvent(new OrderEvent(OrderRefundCompleteListener.MODEL_COMPLETE,bmsDxOrder,orderRefund, ReOrderRefundLog.WX_PAY,refundId));
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

    public boolean refundMoney(BmsDxOrder bmsDxOrder, Double orderRefund, WxPayBean wxPayApiConfig) {
        //执行微信退款
        //订单总金额
        Double orderTotal = ArithUtil.round(ArithUtil.mul(bmsDxOrder.getActualConsum(),100),0);
        String orderTotalFee = String.valueOf(orderTotal.intValue());
        //退款金额
        orderRefund = ArithUtil.round(ArithUtil.mul(orderRefund,100),0);
        if(orderRefund > 0d) {
            String orderRefundFee = String.valueOf(orderRefund.intValue());
            Map<String, String> params = RefundModel.builder()
                    .appid(wxPayApiConfig.getAppId())
                    .mch_id(wxPayApiConfig.getMchId())
                    .nonce_str(WxPayKit.generateStr())
                    .out_trade_no(bmsDxOrder.getOrderNo())
                    .out_refund_no(WxPayKit.generateStr())
                    .total_fee(orderTotalFee)
                    .refund_fee(orderRefundFee)
                    .notify_url(wxPayApiConfig.getRefundNotifyUrl())
                    .build()
                    .createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5);
            String xmlResult = WxPayApi.orderRefund(false, params, wxPayApiConfig.getCertPath(), wxPayApiConfig.getMchId());
            Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
            log.info("wxPay refund result：" + JSON.toJSONString(result));
            String returnCode = result.get("return_code");
            if (bmsDxOrder.getTransactionId() != null && WxPayKit.codeIsOk(returnCode)) {
                String result_code = result.get("result_code");
                if("FAIL".equals(result_code)){
                    String err_code_des = result.get("err_code_des");
                    if("订单已全额退款".equals(err_code_des)){
                        log.info("订单id:{},订单已全额退款",bmsDxOrder.getId());
                        return true;
                    }
                }
                if("SUCCESS".equals(result_code)){
                    String refundId = result.get("refund_id");
                    //查询是否真的退款成功
                    WxRefundQueryBo wxRefundQueryBo = this.refundQuery(refundId,WxPayBeanFactory.MIN_APP_CHANNEL);
                    if(wxRefundQueryBo.checkStatus()){
                        Double refundFree = ArithUtil.div(Double.parseDouble(wxRefundQueryBo.getRefundFee()),100,2);
                        if(refundFree.equals(orderRefund)){
                            //添加一条退款监听
                            BmsCommonService.getApplicationContext().publishEvent(new OrderEvent(OrderRefundCompleteListener.MODEL_COMPLETE,bmsDxOrder,orderRefund, ReOrderRefundLog.WX_PAY,refundId));
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

    public boolean transfersMoneyToCustomerByWxPay(BmsDxOrder bmsDxOrder,String openId,String trueName){
        WxPayApiConfig wxPayApiConfig = getApiConfig(WxPayBeanFactory.MIN_APP_CHANNEL);
        //执行微信退款
        //订单总金额
        log.info("来到这里4");
        Integer transMoneyTotal = ArithUtil.round(ArithUtil.mul(bmsDxOrder.getChangePrice(),100),0).intValue();
        if(transMoneyTotal > 0) {
            log.info("来到这里5");
            String ip = IpKit.getRealIp(RequestParamUtils.getRequest());
            if (StrUtil.isEmpty(ip)) {
                ip = "127.0.0.1";
            }
            Map<String, String> params = TransferModel.builder()
                    .mch_appid(wxPayApiConfig.getAppId())
                    .mchid(wxPayApiConfig.getMchId())
                    .nonce_str(WxPayKit.generateStr())
                    .partner_trade_no(bmsDxOrder.getOrderNo())
                    .openid(openId)
                    .check_name("NO_CHECK")
                    .re_user_name(trueName)
                    .amount(String.valueOf(transMoneyTotal))
                    .desc("觅东东本地生活订单客服代收")
                    .spbill_create_ip(ip)
                    .build()
                    .createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5,false);
            String xmlResult = WxPayApi.transfers(params, wxPayApiConfig.getCertPath(), wxPayApiConfig.getMchId());
            Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
            log.info("转账结果：" + JSON.toJSONString(result));
            String returnCode = result.get("return_code");
            if(WxPayKit.codeIsOk(returnCode) && "SUCCESS".equals(result.get("result_code"))) {
                ReTransferLog reTransferLog = new ReTransferLog();
                reTransferLog.setOrderId(bmsDxOrder.getId());
                reTransferLog.setAppId(wxPayApiConfig.getAppId());
                reTransferLog.setOpenId(openId);
                reTransferLog.setTotal(bmsDxOrder.getChangePrice());
                reTransferLog.setNewTime(new Date());
                reTransferLog.setStatus(Constants.COMMON_FLAG_TRUE_INT);
                reTransferLog.setChannel(ReTransferLogService.CHANNEL_LOCAL_ORDER);
                reTransferLogService.getBaseDao().save(reTransferLog);
                return true;
            }
        }
        return false;
    }

    public boolean transMoneyToPersonal(String transactionId,String outNo,Double transMoney,String account,String remark) {
        WxPayApiConfig wxPayApiConfig = getApiConfig(WxPayBeanFactory.MIN_APP_CHANNEL);
        //执行微信退款
        //订单总金额
        Integer transMoneyTotal = ArithUtil.round(ArithUtil.mul(transMoney,100),0).intValue();
        List<ReceiversModel> receivers = new ArrayList<>();
        //退款金额
        receivers.add(ReceiversModel.builder().type("PERSONAL_WECHATID")
                .account(account).amount(transMoneyTotal).description(remark).build());
        if(transMoneyTotal > 0) {
            Map<String, String> params = ProfitSharingModel.builder()
                    .appid(wxPayApiConfig.getAppId())
                    .mch_id(wxPayApiConfig.getMchId())
                    .nonce_str(WxPayKit.generateStr())
                    .transaction_id(transactionId)
                    .out_order_no(outNo)
                    .receivers(JSON.toJSONString(receivers))
                    .build()
                    .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);
            String xmlResult = WxPayApi.transfers(params, wxPayApiConfig.getCertPath(), wxPayApiConfig.getMchId());
            Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
            log.info("转账结果：" + JSON.toJSONString(result));
            String returnCode = result.get("return_code");
            if(WxPayKit.codeIsOk(returnCode) && "SUCCESS".equals(result.get("result_code"))) {
                return true;
            }
        }
        return false;
    }

    public boolean sharingAddReceiver(Integer handleRece,String type,String account,String name,String relationType) {
        WxPayApiConfig wxPayApiConfig = getApiConfig(WxPayBeanFactory.MIN_APP_CHANNEL);
        if(handleRece == PUBLIC_PAY){
            wxPayApiConfig = getApiConfig(WxPayBeanFactory.PUBLIC_APP_CHANNEL);
        }
        //执行微信退款
        //订单总金额
        /*Integer transMoneyTotal = ArithUtil.round(ArithUtil.mul(transMoney,100),0).intValue();
        ReceiversAddModel receivers = ReceiversAddModel.builder().type(type)
                .account(account).name(name).relationType("HEADQUARTER").build();
        if(transMoneyTotal > 0) {
            Map<String, String> params = ProfitSharingAddModel.builder()
                    .appid(wxPayApiConfig.getAppId())
                    .mch_id(wxPayApiConfig.getMchId())
                    .nonce_str(WxPayKit.generateStr())
                    .receiver(JSON.toJSONString(receivers))
                    .build()
                    .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);
            String xmlResult = WxPayApi.profitSharingAddReceiver(params);
            Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
            log.info("转账结果：" + JSON.toJSONString(result));
            String returnCode = result.get("return_code");
            if(WxPayKit.codeIsOk(returnCode) && "SUCCESS".equals(result.get("result_code"))) {
                return true;
            }
        }*/
        return false;
    }

    public WxPayApiConfig getApiConfig(String channel) {
        WxPayApiConfig apiConfig;
        WxPayBean wxPayBean = WxPayBeanFactory.getProperties(channel);
        try {
            apiConfig = WxPayApiConfigKit.getApiConfig(wxPayBean.getAppId());
        } catch (Exception e) {
            apiConfig = WxPayApiConfig.builder()
                    .appId(wxPayBean.getAppId())
                    .mchId(wxPayBean.getMchId())
                    .partnerKey(wxPayBean.getPartnerKey())
                    .certPath(wxPayBean.getCertPath())
                    .domain(wxPayBean.getDomain())
                    .build();
            WxPayApiConfigKit.putApiConfig(apiConfig);
        }
        return apiConfig;
    }

    public void appPayServicePayNotify(HttpServletRequest request, HttpServletResponse response) {
        String xmlMsg = HttpKit.readData(request);
        log.info("支付通知=" + xmlMsg);
        Map<String, String> params = WxPayKit.xmlToMap(xmlMsg);
        log.info("支付通知json格式：" + JSON.toJSONString(params));
        String returnCode = params.get("return_code");
        Map<String,Object> forwardParams = new HashMap<>();
        forwardParams.putAll(params);
        // 注意重复通知的情况，同一订单号可能收到多次通知，请注意一定先判断订单状态
        // 注意此处签名方式需与统一下单的签名类型一致
        if (WxPayKit.verifyNotify(params, getApiConfig(WxPayBeanFactory.APP_MDD_DATA_BANK_CHANNEL).getPartnerKey(), SignType.HMACSHA256)) {
            if (WxPayKit.codeIsOk(returnCode) && "SUCCESS".equals(params.get("result_code"))) {
                //跳转
                String out_trade_no = params.get("out_trade_no");
                if(RedisTemplateUtils.getRedisTemplate().hasKey(Constants.REDIS_KEY_MICOS_PAY + out_trade_no)){
                    String notifyUrl = RedisTemplateUtils.getRedisTemplate().opsForValue().get(Constants.REDIS_KEY_MICOS_PAY + out_trade_no).toString();
                    if(StringUtils.isNotBlank(notifyUrl)){
                        log.info("appPayServicePayNotify callbackUrl : " + notifyUrl);
                        if(ApplicationContextHolder.getActiveProfile().equals("preo")){
                            //先转到外部
                            String externalURL = "http://dg.syni.com/MDD_API/commonTool/common/forwardingInterface";
                            params.put("notifyUrl",notifyUrl);
                            log.info("支付通知json格式：" + JSON.toJSONString(params));
                            RestTemplateUtils.forwardPost(externalURL,request,params);
                        }else {
                            RestTemplateUtils.forwardPost(notifyUrl,request,params);
                        }
                    }
                }
                Map<String, String> xml = new HashMap<String, String>(2);
                xml.put("return_code", "SUCCESS");
                xml.put("return_msg", "OK");
            }
        }
    }

    public Map<String,Object> transfersMoneyToPersonal(Double transMoney, Integer userId, String withdrawalNo,Integer channel) {
        Optional<BmsUser> bmsUserOptional = bmsUserService.getBaseDao().findById(userId);
        if(!bmsUserOptional.isPresent()){
            return ResultMapHelper.result(ResultCode.CODE_ERROR_100, ResultMsg.CODE_ERROR_PARAM_ERROR);
        }
        BmsUser bmsUser = bmsUserOptional.get();
        String phoneNo = bmsUser.getPhone();
        String openId = null;
        String wxApp = null;
        if(StringUtils.isNotBlank(bmsUser.getMinOpenid())){
            openId = bmsUser.getMinOpenid();
            wxApp = WxPayBeanFactory.MIN_APP_CHANNEL;
        }else if(StringUtils.isNotBlank(bmsUser.getAppOpenid())){
            openId = bmsUser.getAppOpenid();
            wxApp = WxPayBeanFactory.MIDONGDONG_APP_CHANNEL;
        }
        if(StringUtils.isBlank(openId) || StringUtils.isBlank(wxApp)){
            return ResultMapHelper.result(ResultCode.CODE_USER_WX_NO_BIND, ResultMsg.MSG_USER_WX_NO_BIND);
        }
        if(transfersMoneyToPersonal(transMoney,phoneNo,openId,withdrawalNo,channel,wxApp)){
            return ResultMapHelper.success(null);
        }
        return ResultMapHelper.result(ResultCode.CODE_ERROR_100, ResultMsg.CODE_ERROR_PARAM_ERROR);
    }

    public boolean transfersMoneyToPersonal(Double transMoney,String phoneNo,String openId, String withdrawalNo,Integer channel,String wxApp) {
        if(StringUtils.isBlank(withdrawalNo)){
            withdrawalNo = WebUtils.getRandomNoByTime(8);
        }
        WxPayApiConfig wxPayApiConfig = getApiConfig(wxApp);
        //执行微信退款
        //订单总金额
        Integer transMoneyTotal = ArithUtil.round(ArithUtil.mul(transMoney,100),0).intValue();
        if(transMoneyTotal > 0) {
            String ip = IpKit.getRealIp(RequestParamUtils.getRequest());
            if (StrUtil.isEmpty(ip)) {
                ip = "127.0.0.1";
            }
            String desc = "觅东东分销佣金提现";
            if(channel == ReTransferLogService.CHANNEL_LOCAL_ORDER) {
                desc = "本地生活订单转账至客服";
            }
            if(StringUtils.isNotBlank(phoneNo)){
                desc = phoneNo + "-" + desc;
            }
            Map<String, String> params = TransferModel.builder()
                    .mch_appid(wxPayApiConfig.getAppId())
                    .mchid(wxPayApiConfig.getMchId())
                    .nonce_str(WxPayKit.generateStr())
                    .partner_trade_no(withdrawalNo)
                    .openid(openId)
                    .check_name("NO_CHECK")
                    .amount(String.valueOf(transMoneyTotal))
                    .desc(desc)
                    .spbill_create_ip(ip)
                    .build()
                    .createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5,false);
            String xmlResult = WxPayApi.transfers(params, wxPayApiConfig.getCertPath(), wxPayApiConfig.getMchId());
            Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
            log.info("转账结果：" + JSON.toJSONString(result));
            String returnCode = result.get("return_code");
            if(WxPayKit.codeIsOk(returnCode) && "SUCCESS".equals(result.get("result_code"))) {
                ReTransferLog reTransferLog = new ReTransferLog();
                reTransferLog.setAppId(wxPayApiConfig.getAppId());
                reTransferLog.setOpenId(openId);
                reTransferLog.setTotal(transMoney);
                reTransferLog.setNewTime(new Date());
                reTransferLog.setBizNo(withdrawalNo);
                reTransferLog.setStatus(Constants.COMMON_FLAG_TRUE_INT);
                reTransferLog.setChannel(channel);
                reTransferLogService.getBaseDao().save(reTransferLog);
                return true;
            }
        }
        return false;
    }

    public Map<String,Object> orderQuery(String orderNo,String wxApp) {
        Map<String,Object> resultMap = new HashMap<>();
        resultMap.put("isPay",Constants.COMMON_NOKNOW_INT);
        try {
            if(StringUtils.isNotBlank(orderNo)  && StringUtils.isNotBlank(wxApp)) {
                WxPayApiConfig wxPayApiConfig = getApiConfig(wxApp);
                Map<String, String> params = OrderQueryModel.builder()
                        .appid(wxPayApiConfig.getAppId())
                        .mch_id(wxPayApiConfig.getMchId())
                        .out_trade_no(orderNo)
                        .nonce_str(WxPayKit.generateStr())
                        .build()
                        .createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5);
                String xmlResult = WxPayApi.orderQuery(params);
                Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
                log.info("orderQuery result : " + JSON.toJSONString(result));
                String returnCode = result.get("return_code");
                if(WxPayKit.codeIsOk(returnCode) && "SUCCESS".equals(result.get("result_code"))) {
                    String trade_state = result.get("trade_state");
                    if("SUCCESS".equals(trade_state)) {
                        String time_end = result.get("time_end");
                        String tradeNo = result.get("transaction_id");
                        Date date = DateTimeUtils.converStringToDate(time_end,DateTimeUtils.DATE_PATTERN_TIMESTAMP_03);
                        resultMap.put("isPay",Constants.COMMON_FLAG_TRUE_INT);
                        resultMap.put("date",date);
                        resultMap.put("tradeNo",tradeNo);
                        resultMap.put("totalAmount",ArithUtil.div(Double.parseDouble(result.get("total_fee")),100,2));
                    }else if("NOTPAY".equals(trade_state)){
                        resultMap.put("isPay",Constants.COMMON_FLAG_FALSE_INT);
                    }
                }
            }
        }catch (Exception e){
            log.error("wxPay orderQuery error：",e);
        }
        return resultMap;
    }

    public WxRefundQueryBo refundQueryByOrderNo(String orderNo,String refundNum, String wxApp) {
        int count = 10;
        int initQuery = 1;
        WxRefundQueryBo wxRefundQueryBo = new WxRefundQueryBo();
        while (initQuery <= count) {
            try {
                if (StringUtils.isNotBlank(orderNo) && StringUtils.isNotBlank(wxApp)) {
                    WxPayApiConfig wxPayApiConfig = getApiConfig(wxApp);
                    Map<String, String> params = RefundQueryModel.builder()
                            .appid(wxPayApiConfig.getAppId())
                            .mch_id(wxPayApiConfig.getMchId())
                            .out_trade_no(orderNo)
                            .nonce_str(WxPayKit.generateStr())
                            .build()
                            .createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5, false);
                    String xmlResult = WxPayApi.orderRefundQuery(false, params);
                    Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
                    log.info("orderRefundQuery result : " + JSON.toJSONString(result));
                    String returnCode = result.get("return_code");
                    if (WxPayKit.codeIsOk(returnCode) && "SUCCESS".equals(result.get("result_code"))) {

                        String refund_status_0 = result.get("refund_status_0");
                        if ("PROCESSING".equals(refund_status_0)) {
                            Thread.sleep(1000);
                            initQuery++;
                        } else if ("SUCCESS".equals(refund_status_0)) {
                            wxRefundQueryBo.setStatus(Constants.COMMON_FLAG_TRUE_INT);
                            wxRefundQueryBo.setRefundFee(result.get("refund_fee_0"));
                            return wxRefundQueryBo;
                        }else {
                            break;
                        }
                    }
                }
            } catch (Exception e) {
                log.error("wxPay refundQuery error：", e);
            }
        }
        return wxRefundQueryBo;
    }

    public WxRefundQueryBo refundQuery(String refundId, String wxApp) {
        int count = 300;
        int initQuery = 1;
        WxRefundQueryBo wxRefundQueryBo = new WxRefundQueryBo();
        while (initQuery <= count) {
            try {
                if (StringUtils.isNotBlank(refundId) && StringUtils.isNotBlank(wxApp)) {
                    WxPayApiConfig wxPayApiConfig = getApiConfig(wxApp);
                    Map<String, String> params = RefundQueryModel.builder()
                            .appid(wxPayApiConfig.getAppId())
                            .mch_id(wxPayApiConfig.getMchId())
                            .refund_id(refundId)
                            .nonce_str(WxPayKit.generateStr())
                            .build()
                            .createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5, false);
                    String xmlResult = WxPayApi.orderRefundQuery(false, params);
                    Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
                    log.info("orderRefundQuery result : " + JSON.toJSONString(result));
                    String returnCode = result.get("return_code");
                    if (WxPayKit.codeIsOk(returnCode) && "SUCCESS".equals(result.get("result_code"))) {
                        String refund_status_0 = result.get("refund_status_0");
                        if ("PROCESSING".equals(refund_status_0)) {
                            Thread.sleep(1000);
                            initQuery++;
                        } else if ("SUCCESS".equals(refund_status_0)) {
                            wxRefundQueryBo.setStatus(Constants.COMMON_FLAG_TRUE_INT);
                            wxRefundQueryBo.setRefundFee(result.get("refund_fee_0"));
                            return wxRefundQueryBo;
                        }else {
                            break;
                        }
                    }
                }
            } catch (Exception e) {
                log.error("wxPay refundQuery error：", e);
            }
        }
        return wxRefundQueryBo;
    }

    public boolean refundQueryNoWait(String refundId, String wxApp) {
        try {
            if (StringUtils.isNotBlank(refundId) && StringUtils.isNotBlank(wxApp)) {
                WxPayApiConfig wxPayApiConfig = getApiConfig(wxApp);
                Map<String, String> params = RefundQueryModel.builder()
                        .appid(wxPayApiConfig.getAppId())
                        .mch_id(wxPayApiConfig.getMchId())
                        .refund_id(refundId)
                        .nonce_str(WxPayKit.generateStr())
                        .build()
                        .createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5, false);
                String xmlResult = WxPayApi.orderRefundQuery(false, params);
                Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
                log.info("orderRefundQuery result : " + JSON.toJSONString(result));
                String returnCode = result.get("return_code");
                if (WxPayKit.codeIsOk(returnCode) && "SUCCESS".equals(result.get("result_code"))) {
                    String refund_status_0 = result.get("refund_status_0");
                    return "SUCCESS".equals(refund_status_0);
                }
            }
        } catch (Exception e) {
            log.error("refundQueryNoWait error：",e);
        }
        return false;
    }
}
